package com.cicigodd.brick.plug.system.menu.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.cicigodd.brick.plug.common.exception.BusinessException;
import com.cicigodd.brick.plug.common.factory.PageFactory;
import com.cicigodd.brick.plug.common.factory.PageResultFactory;
import com.cicigodd.brick.plug.common.response.PageResult;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cicigodd.brick.plug.common.tree.factory.DefaultTreeBuildFactory;
import com.cicigodd.brick.plug.common.tree.factory.node.SystemTreeConstants;
import com.cicigodd.brick.plug.common.tree.node.ElementTreeNode;
import com.cicigodd.brick.plug.system.menu.entity.SysMenu;
import com.cicigodd.brick.plug.system.menu.factory.EleMenusFactory;
import com.cicigodd.brick.plug.system.menu.response.RouterResponse;
import com.cicigodd.brick.plug.system.menu.response.SysMenuDetailResponse;
import com.cicigodd.brick.plug.system.menu.response.SysMenuListResponse;
import com.cicigodd.brick.plug.system.menu.request.SysMenuAddRequest;
import com.cicigodd.brick.plug.system.menu.request.SysMenuDeleteRequest;
import com.cicigodd.brick.plug.system.menu.request.SysMenuDetailRequest;
import com.cicigodd.brick.plug.system.menu.request.SysMenuEditRequest;
import com.cicigodd.brick.plug.system.menu.request.SysMenuListRequest;
import com.cicigodd.brick.plug.system.menu.mapper.SysMenuMapper;
import com.cicigodd.brick.plug.system.menu.service.SysMenuService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Arrays;

/**
 * 菜单管理
 *
 * @author cicigodd
 * @date 2022/12/12 16:28:23
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {

    /**
     * 添加
     *
     * @author cicigodd
     * @date 2022/12/12 16:28:23
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(SysMenuAddRequest sysMenuAddRequest) {
        // 如果父节点为空，则填充为默认的父节点id
        if (ObjectUtil.isNull(sysMenuAddRequest.getParentId())) {
            sysMenuAddRequest.setParentId(SystemTreeConstants.DEFAULT_PARENT_ID);
        } else {
            // 如果父节点不为空，并且不是-1，则判断父节点存不存在，防止脏数据
            if (!SystemTreeConstants.DEFAULT_PARENT_ID.equals(sysMenuAddRequest.getParentId())) {
                SysMenu sysMenu = this.getById(sysMenuAddRequest.getParentId());
                if (ObjectUtil.isNull(sysMenu)) {
                    throw new BusinessException("上级菜单不存在，请检查数据");
                }
            }
        }

        SysMenu sysMenu = new SysMenu();
        BeanUtil.copyProperties(sysMenuAddRequest, sysMenu);

        // 组装pids
        String newPids = createPids(sysMenuAddRequest.getParentId());
        sysMenu.setMenuPids(newPids);

        this.save(sysMenu);
    }

    /**
     * 创建pids的值
     * 如果pid是0顶级节点，pids就是 [-1],
     * 如果pid不是顶级节点，pids就是父菜单的pids + [pid] + ,
     */
    private String createPids(Integer pid) {
        if (pid.equals(SystemTreeConstants.DEFAULT_PARENT_ID)) {
            return "[" + SystemTreeConstants.DEFAULT_PARENT_ID + "]" + ",";
        } else {
            //获取父菜单
            SysMenu parentMenu = this.getById(pid);

            // 组装pids
            return parentMenu.getMenuPids() + "[" + pid + "]" + ",";
        }
    }


    /**
     * 删除
     *
     * @author cicigodd
     * @date 2022/12/12 16:28:23
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(SysMenuDeleteRequest sysMenuDeleteRequest) {
        LambdaQueryWrapper<SysMenu> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(SysMenu::getParentId, sysMenuDeleteRequest.getIds());
        List<SysMenu> list = this.list(wrapper);
        if (list.size() > 0) {
            throw new BusinessException("此菜单下含有子菜单，请先删除子菜单");
        }
        this.removeByIds(sysMenuDeleteRequest.getIds());
    }


    /**
     * 编辑
     *
     * @author cicigodd
     * @date 2022/12/12 16:28:23
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void edit(SysMenuEditRequest sysMenuEditRequest) {
        SysMenu sysMenu = this.getById(sysMenuEditRequest.getId());
        if (ObjectUtil.isEmpty(sysMenu)) {
            throw new BusinessException("查询结果不存在");
        }
        BeanUtil.copyProperties(sysMenuEditRequest, sysMenu);
        String newPids = this.createPids(sysMenuEditRequest.getParentId());
        sysMenu.setMenuPids(newPids);
        this.updateById(sysMenu);
    }

    /**
     * 详情
     *
     * @author cicigodd
     * @date 2022/12/12 16:28:23
     */
    @Override
    public SysMenuDetailResponse detail(SysMenuDetailRequest sysMenuDetailRequest) {
        SysMenu sysMenu = this.getById(sysMenuDetailRequest.getId());
        if (ObjectUtil.isEmpty(sysMenu)) {
            throw new BusinessException("查询结果不存在");
        }
        SysMenuDetailResponse sysMenuDetailResponse = new SysMenuDetailResponse();
        BeanUtil.copyProperties(sysMenu, sysMenuDetailResponse);
        return sysMenuDetailResponse;
    }

    /**
     * 列表
     *
     * @author cicigodd
     * @date 2022/12/12 16:28:23
     */
    @Override
    public PageResult<SysMenuListResponse> list(SysMenuListRequest sysMenuListRequest) {
        LambdaQueryWrapper<SysMenu> wrapper = new LambdaQueryWrapper<>();
        Integer parentId = sysMenuListRequest.getParentId();
        String menuPids = sysMenuListRequest.getMenuPids();
        String menuName = sysMenuListRequest.getMenuName();
        String menuType = sysMenuListRequest.getMenuType();
        Integer sort = sysMenuListRequest.getSort();
        String icon = sysMenuListRequest.getIcon();
        String router = sysMenuListRequest.getRouter();
        String component = sysMenuListRequest.getComponent();
        String perms = sysMenuListRequest.getPerms();
        String visible = sysMenuListRequest.getVisible();

        wrapper.eq(ObjectUtil.isNotNull(parentId), SysMenu::getParentId, parentId);
        wrapper.like(ObjectUtil.isNotEmpty(menuPids), SysMenu::getMenuPids, menuPids);
        wrapper.like(ObjectUtil.isNotEmpty(menuName), SysMenu::getMenuName, menuName);
        wrapper.like(ObjectUtil.isNotEmpty(menuType), SysMenu::getMenuType, menuType);
        wrapper.eq(ObjectUtil.isNotNull(sort), SysMenu::getSort, sort);
        wrapper.like(ObjectUtil.isNotEmpty(icon), SysMenu::getIcon, icon);
        wrapper.like(ObjectUtil.isNotEmpty(router), SysMenu::getRouter, router);
        wrapper.like(ObjectUtil.isNotEmpty(component), SysMenu::getComponent, component);
        wrapper.like(ObjectUtil.isNotEmpty(perms), SysMenu::getPerms, perms);
        wrapper.like(ObjectUtil.isNotEmpty(visible), SysMenu::getVisible, visible);
        IPage<SysMenuListResponse> page = this.page(PageFactory.defaultPage(sysMenuListRequest.getPageNum(), sysMenuListRequest.getPageSize()), wrapper).convert(SysMenu -> BeanUtil.copyProperties(SysMenu, SysMenuListResponse.class));
        return PageResultFactory.createPageResult(page);
    }

    @Override
    public List<RouterResponse> getRouters() {
        LambdaQueryWrapper<SysMenu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.and(wrapper -> wrapper.eq(SysMenu::getMenuType, "M").or().eq(SysMenu::getMenuType, "C"));
        queryWrapper.orderByAsc(SysMenu::getSort);
        List<SysMenu> list = this.list(queryWrapper);
        return EleMenusFactory.createTotalMenus(list);
    }

    @Override
    public List<ElementTreeNode> tree() {
        List<ElementTreeNode> menuTreeNodeList = CollectionUtil.newArrayList();
        // 添加根节点
        ElementTreeNode rootNode = EleMenusFactory.createRootNode();
        menuTreeNodeList.add(rootNode);

        LambdaQueryWrapper<SysMenu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByAsc(SysMenu::getSort);
        this.list(queryWrapper).forEach(sysMenu -> {
            ElementTreeNode menuTreeNode = EleMenusFactory.parseMenuBaseTreeNode(sysMenu);
            menuTreeNodeList.add(menuTreeNode);
        });
        // -2是根节点的上级
        return new DefaultTreeBuildFactory<ElementTreeNode>(SystemTreeConstants.VIRTUAL_ROOT_PARENT_ID.toString()).doTreeBuild(menuTreeNodeList);
    }

    @Override
    public List<ElementTreeNode> treeAll() {
        List<ElementTreeNode> menuTreeNodeList = CollectionUtil.newArrayList();
        LambdaQueryWrapper<SysMenu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByAsc(SysMenu::getSort);
        this.list(queryWrapper).forEach(sysMenu -> {
            ElementTreeNode menuTreeNode = EleMenusFactory.parseMenuBaseTreeNode(sysMenu);
            menuTreeNodeList.add(menuTreeNode);
        });
        // -2是根节点的上级
        return new DefaultTreeBuildFactory<ElementTreeNode>(SystemTreeConstants.DEFAULT_PARENT_ID.toString()).doTreeBuild(menuTreeNodeList);

    }
}
